/**
 *
 * 版权所有 © cybersky.com
 *
 */
package cn.cybertron.primus.report.custom.helper;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.nutz.ioc.Ioc;
import org.nutz.json.Json;
import org.nutz.json.JsonFormat;
import org.nutz.lang.Lang;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.nutz.mvc.upload.TempFile;

import cn.cybertron.primus.base.ChartType;
import cn.cybertron.primus.report.entity.ReportObject;
import cn.cybertron.primus.report.cache.ReportCacheManager;
import cn.cybertron.primus.report.custom.ReportCustomHelper;
import cn.cybertron.primus.report.data.ReportCacheSimple;
import cn.cybertron.primus.report.entity.ReportCache;
import cn.cybertron.primus.report.entity.ReportCache.CacheType;
import cn.cybertron.primus.report.entity.ReportChart;
import cn.cybertron.primus.report.entity.ReportPage;

/**
 * 报表自定义助手抽象实现类
 * 
 * @author ch
 *
 */
public abstract class AbstractReportCustomHelper implements ReportCustomHelper {
	
	private static final Log log = Logs.get();

	/**
	 * 常量，过滤条件对象存放在session中的属性名
	 */
	public static final String SESSION_KEY_FILTER = "com.cybertron.primus.report.custom.filter.defination";
	

	/**
	 * 获取type=CacheType.source的中间表的基本信息
	 * @return
	 */
	public static List<ReportCacheSimple> getSourceCaches() {
		List<ReportCacheSimple> simpleCaches = new ArrayList<ReportCacheSimple>();
		List<ReportCache> cacheList = ReportCacheManager.me().availabelCaches();
		if(!Lang.isEmpty(cacheList)){
			for(ReportCache cache: cacheList) {
				if(cache.getType() == CacheType.source) {	
					simpleCaches.add(new ReportCacheSimple(cache));
				}
			}
		}
		
		return simpleCaches;
	}
	
	/**
	 * 将report对象保存到request中，方便修改
	 * 
	 * @param ioc
	 * @param request
	 * @param response
	 * @return
	 */
	public void prepareBasicInfo(ReportObject report, HttpServletRequest request, Ioc ioc) {
		if(report != null)
			request.setAttribute("report", report);
	}
	
	/**
	 * 为setChart()方法准备params参数
	 * 
	 * @param ioc
	 * @param request
	 * @param response
	 * @return
	 */
	public abstract Map<String, Object> prepareChartParams(Ioc ioc, HttpServletRequest request, HttpServletResponse response);

	/**
	 * 为setPage()方法准备params参数
	 * 
	 * @param ioc
	 * @param request
	 * @param response
	 * @return
	 */
	@Override
	public Map<String, Object> preparePageParams(Ioc ioc, HttpServletRequest request, HttpServletResponse response){
		Map<String, Object> params = new HashMap<String, Object>();
		TempFile headerLogo = (TempFile)request.getAttribute("header_icon");
		TempFile footerLogo = (TempFile)request.getAttribute("footer_icon");
		params.put("headerLogo", headerLogo);
		params.put("footerLogo", footerLogo);
		return params;
	}

	/**
	 * 根据表示报表数据源的json字符串设置Report对象的数据源信息
	 * 
	 * @param report
	 *            Report对象
	 * @param jsonQuery
	 *            表示报表数据源的json字符串
	 * @param params
	 *            其它需要的参数
	 */
	public abstract void setQuery(ReportObject report, String jsonQuery, Map<String, Object> params);

	/**
	 * 根据表示报表统计图的json字符串设置Report对象的统计图信息
	 * 
	 * @param report
	 *            Report对象
	 * @param jsonChart
	 *            表示报表统计图的json字符串
	 * @param params
	 *            其它需要的参数
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public void setChart(ReportObject report, String jsonChart, Map<String, Object> params){
		if(report == null || jsonChart == null || jsonChart.trim().length() == 0)
			return;
		
		Map map = (Map)Json.fromJson(jsonChart);
		String charttype = (String)map.get("charttype");
		int topn = 0;
		if(map.get("topn") != null)
			topn = Integer.valueOf(String.valueOf(map.get("topn")));
		String group1 = (String)map.get("group1");
		String group2 = (String)map.get("group2");
		Map<String, String> series = (Map<String, String>)map.get("series");
		
		ReportChart chart = new ReportChart(ChartType.valueOf(charttype));
		chart.setTopN(topn);
		List<String> groupNames = new ArrayList<String>();
		chart.setGroupNames(groupNames);
		if(chart.getChartType().equals(ChartType.TIMESERIES)){
			String timeColumnName = getTimeColumnName();
			if(timeColumnName == null) {
				log.error("No time column specified for timeseries chart");
				return;
			}
			groupNames.add(timeColumnName);
		}
		if(group1 != null && group1.trim().length() > 0)
			groupNames.add(group1);
		if(group2 != null && group2.trim().length() > 0)
			groupNames.add(group2);
		
		LinkedHashMap<String, String> serieMap = new LinkedHashMap<String, String>();
		chart.setSerieInfo(serieMap);
		for(String serie: series.keySet()) {
			serieMap.put(serie, series.get(serie));
		}
		
		String charttitle = (String) map.get("charttitle");
		if(charttitle != null && !charttitle.equals(""))
			chart.setChartTitle(charttitle);
		
		String chartAsc = (String) map.get("chartAsc");
		if(chartAsc != null && !chartAsc.equals("")) {
			chart.setChartAsc(chartAsc);
		}
		
		report.addChart(chart);
	}

	/**
	 * 时间序列图使用的时间字段名
	 * @return
	 */
	public abstract String getTimeColumnName();

	/**
	 * 根据表示报表页面设置的json字符串设置Report对象的页面设置信息
	 * 
	 * @param report
	 *            Report对象
	 * @param jsonPage
	 *            表示报表页面设置的json字符串
	 * @param params
	 *            其它需要的参数
	 */
	public void setPage(ReportObject report, String jsonPage, Map<String, Object> params) {
		if(params == null)
			params = new HashMap<String, Object>();
		
		ReportPage page = Json.fromJson(ReportPage.class, jsonPage);
		
		report.setPage(page);
	}

	/**
	 * 根据Report对象得到表示报表数据源的json字符串
	 * 
	 * @param report
	 *            Report对象
	 * @return 表示报表数据源的json字符串
	 */
	public abstract String getQueryStr(ReportObject report);

	/**
	 * 根据Report对象得到表示报表统计图的json字符串
	 * 
	 * @param report
	 *            Report对象
	 * @return 表示报表统计图的json字符串
	 */
	public String getChartStr(ReportObject report){
		String str = "";
		if(report != null) {
			List<ReportChart> charts = report.getCharts();
			if(!Lang.isEmpty(charts))
				str = Json.toJson(charts, JsonFormat.compact());
		}
		
		return str;
	}

	/**
	 * 根据Report对象得到表示报表页面设置的json字符串
	 * 
	 * @param report
	 *            Report对象
	 * @return 表示报表页面设置的json字符串
	 */
	public String getPageStr(ReportObject report){
		String str = "";
		if(report != null) {
			ReportPage page = report.getPage();
			str = Json.toJson(page, JsonFormat.compact());
		}
		
		return str;
	}

	/**
	 * 实现此抽象方法来为统计图页面准备数据。
	 * 前3个参数传入时为空列表，方法实现的目的就是填充这3个列表，为统计图页面准备数据
	 * @param chartTypes 支持的统计图类型，列表元素为统计图类型枚举值
	 * @param groupItems 分组项，列表元素为{name:xx, text:yy}形式的Map|Object
	 * @param statItems 统计项，列表元素为{name:xx, text:yy, statName:zz}形式的Map|Object
	 * @param report 报表对象
	 */
	protected abstract void prepareChart(List<ChartType> chartTypes, List<String> groupItems, List<String> statItems, ReportObject report);
	
}
